﻿using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using System.Text.RegularExpressions;
using System.Text;
using System.Web;
using System.Net;
using Microsoft.SharePoint.Taxonomy;
using System.Collections.Generic;
using System.Globalization;
using System.Collections;
using System.Configuration;
using System.Linq;

namespace beyCoo4Sharepoint.beyCooEventReceiver
{
    /// <summary>
    /// List Item Events
    /// </summary>
    public class beyCooEventReceiver : SPItemEventReceiver
    {
        private string customerKey;
        private string serviceKey;
        private string serviceType;
        private string serverName;
        private string currentList;
        private List<string> xPathEntity = new List<string>();
        private string xPathRTF;
        bool checkboxBeyCooActive;
        string listMapping;
        string selectedSourceColumn;
        string requestedService;
        private Hashtable mapping = new Hashtable();
        private List<Term> columnTermSet = new List<Term>();
        private Hashtable availableServices = new Hashtable();
        private bool useHttpsChoice = true;
        //private Hashtable colTermSetForOnUpdate = new Hashtable();
        private StringBuilder colTermSetForOnupdate = new StringBuilder();
        private string columnsForOnUpdate;
        private List<Term> newlyAddedTerms = new List<Term>();

        /// <summary>
        /// event receiver method, designed to facilitate beyCoo for SPList objects and SPDocumentLibraries.
        /// first we load the settings from the settings list, if any, and proceed with the desired service (RTF or Entity Extraction).
        /// </summary>
        /// <param name="properties"></param>
        public override void ItemAdded(SPItemEventProperties properties)
        {
            beyCooLogger.LogMessage("beyCooMessage", "item was added, event receiver started");
            SPWeb web = properties.ListItem.Web;
            serverName = web.Url;
            //check if the customer key for beyCoo is present in web.Properties
            if (web.Properties.ContainsKey(beyCooConstants.beyCooCustomerKey))
            {
                customerKey = web.Properties[beyCooConstants.beyCooCustomerKey].ToString();

                if (customerKey.Length > 0)
                {
                    //check if Https is being requested
                    //if (web.Properties.ContainsKey(beyCooConstants.beyCooUseHttpsChoice))
                    //{
                    //    useHttpsChoice = Boolean.Parse(web.Properties[beyCooConstants.beyCooUseHttpsChoice].ToString());
                    //}

                    if (web.Properties.ContainsKey(beyCooConstants.beyCooUseHttpsChoice))
                    {
                        web.Properties[beyCooConstants.beyCooUseHttpsChoice] = useHttpsChoice.ToString();
                    }
                    else
                    {
                        web.Properties.Add(beyCooConstants.beyCooUseHttpsChoice, useHttpsChoice.ToString());
                    }
                    web.Properties.Update();

                    currentList = properties.List.Title.ToString();
                    //do not apply beyCoo to the beyCoo settings  list itself
                    if (!currentList.Equals(beyCooConstants.settingsListTitle))
                    {

                        SPList settingsList = web.Lists[beyCooConstants.settingsListTitle];
                        SPView view = settingsList.DefaultView;
                        SPListItemCollection itemCol = settingsList.GetItems(view);
                        foreach (SPListItem item in itemCol)
                        {
                            SPListItem item2 = settingsList.GetItemById(item.ID);
                            if (item2[beyCooConstants.settingsListColName].Equals(currentList))
                            {
                                //Load all the settings for this list item from the settings list
                                loadSettingsFromSettingsList(item2);
                                //get the available services for this customerkey
                                getService(useHttpsChoice, web);

                                //check if beyCoo is active for the current list, of so, start the requested service
                                if (checkboxBeyCooActive)
                                {
                                    //differentiate between SPDocumentLibraries and SPLists
                                    if (properties.List is SPDocumentLibrary)
                                    {
                                        //part for SPDocLib, uploaded file will be attained over webrequest, converted to correct format and transferred to beyCoo webservice
                                        string fileurl = properties.AfterUrl;
                                        //create webrequest and get back webresponse from beyCoo
                                        //handle according to available services for this customerkey

                                        if (serviceType.Equals(beyCooConstants.serviceChoiceEntity) && serviceKey.Length > 0)
                                        {
                                            beyCooObject beyCoo_file = new beyCooObject(fileurl, true, customerKey, serviceKey, serverName, xPathEntity);
                                            //parse the response to a hashtable, extract entities
                                            entityExtraction(beyCoo_file.entities, properties);
                                        }
                                        if (serviceType.Equals(beyCooConstants.serviceChoiceRTF) && serviceKey.Length > 0)
                                        {
                                            xPathRTF = xPathEntity[0].ToString();
                                            beyCooObject beyCoo_file = new beyCooObject(fileurl, true, customerKey, serviceKey, serverName, xPathRTF);
                                            //parse the response to a hashtable, extract relevant terms
                                            entityExtraction(beyCoo_file.rtf, properties);
                                        }

                                    }
                                    else
                                    {
                                        //part for SPlist, contents of selected source column will be converted to correct format and transferred to beyCoo webservice 
                                        if (selectedSourceColumn.Length > 0)
                                        {

                                            string uebergabe = properties.AfterProperties[selectedSourceColumn].ToString();
                                            //create webrequest and get back webresponse from beyCoo

                                            if (serviceType.Equals(beyCooConstants.serviceChoiceEntity) && serviceKey.Length > 0)
                                            {
                                                beyCooObject beyCoo = new beyCooObject(uebergabe, customerKey, serviceKey, serverName, xPathEntity);
                                                //parse the response to a hashtable, extract entities
                                                entityExtraction(beyCoo.entities, properties);
                                            }
                                            if (serviceType.Equals(beyCooConstants.serviceChoiceRTF) && serviceKey.Length > 0)
                                            {
                                                xPathRTF = xPathEntity[0].ToString();
                                                beyCooObject beyCoo = new beyCooObject(uebergabe, customerKey, serviceKey, serverName, xPathRTF);
                                                //parse the response to a hashtable, extract relevant terms
                                                entityExtraction(beyCoo.rtf, properties);
                                            }

                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    beyCooLogger.LogError("beyCooError", "No customer key is present, check beyCoo4Sharepoint plugin settings for key");
                }
            }
            else
            {
                beyCooLogger.LogError("beyCooError", "No customer key is present, check beyCoo4Sharepoint plugin settings for key");
            }
            web.Dispose();
            base.ItemAdded(properties);
        }



        /// <summary>
        /// event receiver method, designated to facilitate beyCoo for wiki/site pages, list name "Site Pages"
        /// first we load the settings from the settin  1gs list, if any, and proceed with the desired service (RTF or Entity Extraction).
        /// </summary>
        /// <param name="properties"></param>
        public override void ItemUpdated(SPItemEventProperties properties)
        {

            if (properties.Web.Properties.ContainsKey(beyCooConstants.beyCooCurrentColumns))
            {
                columnsForOnUpdate = properties.Web.Properties[beyCooConstants.beyCooCurrentColumns].ToString();
            }
            int i = 0;
            foreach (SPField fld in properties.List.Fields)
            {
                if (fld is Microsoft.SharePoint.Taxonomy.TaxonomyField)
                {
                    i++;
                }
            }
            int nrOfMetaDataCols = i;
            string[] sep1 = { ";#" };
            string[] cols = columnsForOnUpdate.Split(sep1, StringSplitOptions.RemoveEmptyEntries);

            //part for deleting terms from termstore that user decides to manually delete before saving the item to the list with its properties
            if (columnsForOnUpdate.Length > 0 && nrOfMetaDataCols == cols.Length)
            {
                //fill teststring with values of last metadata column in the list
                string termsincol = properties.ListItem[cols[cols.Length - 1]].ToString();

                if (termsincol.Length > 0)
                {

                    //get the set of terms that the plugin wrote in the columns and compare it to the set of terms the user has made out of it, 
                    //only save the terms to the term set that the user wants, so if the user manually deletes terms, this means deleting those terms 
                    //from the term set, if this was a freshly added term

                    foreach (string colname in cols)
                    {
                        string[] beyCooTermsSeparated = { };
                        List<string> beycooColl = new List<string>();
                        IEnumerable<string> termsToDelete = new List<string>();
                        string[] sepTerms = { ";" };
                        if (properties.Web.Properties.ContainsKey(beyCooConstants.beyCooColTerms + colname))
                        {
                            //get the variable in the property bag containing the terms for this column
                            string beyCooTerms = properties.Web.Properties[beyCooConstants.beyCooColTerms + colname].ToString();
                            //first test if the collection of terms in the column is equal to the collection of terms added by the plugin (user made no changes -> don't act)
                            beyCooTermsSeparated = beyCooTerms.Split(sepTerms, StringSplitOptions.RemoveEmptyEntries);
                        }
                        foreach (string t in beyCooTermsSeparated)
                        {
                            beycooColl.Add(t);
                        }

                        //still needs further testing, list items are not always read out correctly: when the plugin provisioned terms A, B and C in a TaxField,
                        //and the user deletes term A before saving, sometimes properties.ListItem[colname] equals A, B, instead of B, C!!!!
                        string[] userTermsSeparated = properties.ListItem[colname].ToString().Split(sepTerms, StringSplitOptions.RemoveEmptyEntries);
                        List<string> userColl = new List<string>();
                        foreach (string s in userTermsSeparated)
                        {
                            if (s.Contains("|"))
                            {
                                userColl.Add(s);
                            }
                        }

                        //now compare the two string lists
                        IEnumerable<string> diffList = beycooColl.Except(userColl);

                        if (diffList.Count<string>() > 0)
                        {
                            //collections from beycoo and from user are different for this column, user has deleted terms from the current column
                            //find out if these terms are freshly added terms -> delete from termset
                            if (properties.Web.Properties.ContainsKey(beyCooConstants.beyCooFreshTerm + colname))
                            {
                                string freshlyAddedTerms = properties.Web.Properties[beyCooConstants.beyCooFreshTerm + colname].ToString();
                                string[] freshlyAddedTermsSeparated = freshlyAddedTerms.Split(sepTerms, StringSplitOptions.RemoveEmptyEntries);
                                if (freshlyAddedTermsSeparated.Length > 0)
                                {

                                    termsToDelete = diffList.Intersect<string>(freshlyAddedTermsSeparated);

                                    //open termset for this column and delete fresh term

                                    //instantiate the taxonomyfield, session and store for the current entity/managed metadata column
                                    TaxonomyField tagsField = (TaxonomyField)properties.List.Fields[colname];
                                    TaxonomySession session = new TaxonomySession(properties.Web.Site);
                                    TermStore termStore = session.TermStores[tagsField.SspId];

                                    //get the termSet for the current entity/managed metadata column
                                    TermSet termSet = termStore.GetTermSet(tagsField.TermSetId);
                                    foreach (string d in termsToDelete)
                                    {
                                        string[] sepInnerTerm = { "|" };
                                        string[] termToDel = d.Split(sepInnerTerm, StringSplitOptions.RemoveEmptyEntries);
                                        string termToDelName = termToDel[0];
                                        Term termToDelete = termSet.Terms[termToDelName];
                                        try
                                        {
                                            //this piece of the code only works for admins, can't seem to get it to work for normal user, not even with Elevated Privileges..
                                            //SPSecurity.RunWithElevatedPrivileges(delegate()
                                            //{
                                            termStore.AddTermStoreAdministrator(properties.UserLoginName);
                                            termStore.CommitAll();
                                            termToDelete.Delete();
                                            termStore.DeleteTermStoreAdministrator(properties.UserLoginName);
                                            termStore.CommitAll();
                                            //});
                                        }
                                        catch (Exception e)
                                        {
                                            beyCooLogger.LogError("beyCooError", e.Message + " - " + e.StackTrace);
                                        }
                                    }
                                    termStore.CommitAll();

                                }
                            }

                        }
                    }
                }
            }
            //reset the variables in the propertybag for next run
            resetVars(properties, cols);
            colTermSetForOnupdate.Remove(0, colTermSetForOnupdate.Length);


            //normal part for beycoo onupdate
            SPWeb web = properties.ListItem.Web;
            serverName = web.Url;
            //check if the customer key for beyCoo is present in web.Properties
            if (web.Properties.ContainsKey(beyCooConstants.beyCooCustomerKey))
            {
                customerKey = web.Properties[beyCooConstants.beyCooCustomerKey].ToString();
                if (customerKey.Length > 0)
                {

                    //if (web.Properties.ContainsKey(beyCooConstants.beyCooUseHttpsChoice))
                    //{
                    //    useHttpsChoice = Boolean.Parse(web.Properties[beyCooConstants.beyCooUseHttpsChoice].ToString());
                    //}

                    if (web.Properties.ContainsKey(beyCooConstants.beyCooUseHttpsChoice))
                    {
                        web.Properties[beyCooConstants.beyCooUseHttpsChoice] = useHttpsChoice.ToString();
                    }
                    else
                    {
                        web.Properties.Add(beyCooConstants.beyCooUseHttpsChoice, useHttpsChoice.ToString());
                    }
                    web.Properties.Update();

                    currentList = "Site Pages";

                    if (properties.ListTitle.Equals(currentList))
                    {
                        SPList settingsList = web.Lists[beyCooConstants.settingsListTitle];
                        SPView view = settingsList.DefaultView;
                        SPListItemCollection itemCol = settingsList.GetItems(view);
                        foreach (SPListItem item in itemCol)
                        {
                            SPListItem item2 = settingsList.GetItemById(item.ID);
                            if (item2[beyCooConstants.settingsListColName].Equals(currentList))
                            {
                                //Load all the settings for this list item from the settings list
                                loadSettingsFromSettingsList(item2);
                                //get the available services for this customerkey
                                getService(useHttpsChoice, web);

                                //check if beyCoo is active for the current list, of so, start the requested service
                                if (checkboxBeyCooActive)
                                {

                                    SPListItem li = properties.ListItem;
                                    //get the contents of the "wikifield" to send to beyCoo, as this field contains the contents of the page (html)
                                    string wikiContent = li["WikiField"].ToString();
                                    //instantiate beyCoo with wikiContent

                                    if (serviceType.Equals(beyCooConstants.serviceChoiceEntity) && serviceKey.Length > 0)
                                    {
                                        beyCooObject beyCoo = new beyCooObject(wikiContent, customerKey, serviceKey, serverName, xPathEntity);
                                        //parse the response to a hashtable, extract entities
                                        entityExtraction(beyCoo.entities, properties);
                                    }
                                    if (serviceType.Equals(beyCooConstants.serviceChoiceRTF) && serviceKey.Length > 0)
                                    {
                                        xPathRTF = xPathEntity[0].ToString();
                                        beyCooObject beyCoo = new beyCooObject(wikiContent, customerKey, serviceKey, serverName, xPathRTF);
                                        //parse the response to a hashtable, extract relevant terms
                                        entityExtraction(beyCoo.rtf, properties);
                                    }

                                }

                            }

                        }
                    }
                }
                else
                {
                    beyCooLogger.LogError("beyCooError", "No customer key is present, check beyCoo4Sharepoint plugin settings for key");
                }
            }
            else
            {
                beyCooLogger.LogError("beyCooError", "No customer key is present, check beyCoo4Sharepoint plugin settings for key");
            }
            web.Dispose();
            base.ItemUpdated(properties);
        }


        /// <summary>
        /// reset the variables in the propertybag that are used to identify terms deleted by the user before saving the terms with the uploaded document.
        /// </summary>
        /// <param name="properties"></param>
        /// <param name="cols"></param>
        private void resetVars(SPItemEventProperties properties, string[] cols)
        {
            using (SPWeb web = properties.Web)
            {
                web.AllowUnsafeUpdates = true;
                foreach (string colname in cols)
                {
                    if (web.Properties.ContainsKey(beyCooConstants.beyCooColTerms + colname))
                    {
                        web.Properties[beyCooConstants.beyCooColTerms + colname] = null;
                    }
                    if (properties.Web.Properties.ContainsKey(beyCooConstants.beyCooFreshTerm + colname))
                    {
                        web.Properties[beyCooConstants.beyCooFreshTerm + colname] = null;
                    }
                }
                web.Properties.Update();
                web.AllowUnsafeUpdates = true;
            }
        }


        /// <summary>
        /// read the settings from the current item in the beyCoo Settings list
        /// </summary>
        /// <param name="item2"></param>
        private void loadSettingsFromSettingsList(SPListItem item2)
        {
            //load settings from settings list for the current list for which beyCoo should become active
            checkboxBeyCooActive = Boolean.Parse(item2[beyCooConstants.settingsListColActive].ToString());

            if (item2[beyCooConstants.settingsListColSource] != null && item2[beyCooConstants.settingsListColSource].ToString().Length > 0)
            {
                selectedSourceColumn = item2[beyCooConstants.settingsListColSource].ToString();
            }

            if (item2[beyCooConstants.settingsListColMapping] != null && item2[beyCooConstants.settingsListColMapping].ToString().Length > 0)
            {
                listMapping = item2[beyCooConstants.settingsListColMapping].ToString();
            }

            if (listMapping != null && listMapping.Length > 0)
            {
                xPathEntity.Clear();
                string[] valssep = { "\r\n", "\n" };
                string[] vals = listMapping.Split(valssep, StringSplitOptions.RemoveEmptyEntries);
                foreach (string val in vals)
                {
                    xPathEntity.Add(val);
                }

            }
            requestedService = item2[beyCooConstants.settingsListColService].ToString();
        }


        private void getService(bool useHttpsChoice, SPWeb web)
        {
            //get available services over a webrequest
            beyCooConnection beycooCon = new beyCooConnection();
            string serviceURL = "";
            //get the serviceURL and complete it
            if (useHttpsChoice)
            {
                serviceURL = beyCooConstants.beyCooServiceURLhttps + customerKey + "/services.xml";
            }
            else
            {
                serviceURL = beyCooConstants.beyCooServiceURL + customerKey + "/services.xml";
            }

            //get available services from the webservice for this customerkey
            availableServices = beycooCon.getServices(serviceURL, serverName, web);
            // fill servicekeys out of resulting hashtable
            foreach (DictionaryEntry service in availableServices)
            {
                if (service.Key.ToString().Equals(requestedService))
                {
                    //check the type of the requested service, then split service.key on "|" and take second part, which contains the servicekey
                    string[] sepService = { "|" };
                    string[] serviceTypeAndKey = service.Value.ToString().Split(sepService, StringSplitOptions.RemoveEmptyEntries);

                    serviceType = serviceTypeAndKey[0].ToString();
                    serviceKey = serviceTypeAndKey[1].ToString();
                }

            }
        }


        /// <summary>
        /// main loop for entity extraction, takes the parsed webresponse as input (hashtable containing all entities) and extracts the entities or relevant terms.
        /// the loop is repeated per entity, where each entity equals a managed metadata column in the target list.
        /// the method calls submethods to add the entity terms to the termset for the managed metadata columns as well as for adding the terms (per termset) 
        /// to the column in the target list (as tags).
        /// </summary>
        /// <param name="_beycooInputHash"></param>
        /// <param name="properties"></param>
        private void entityExtraction(Hashtable _beycooInputHash, SPItemEventProperties properties)
        {

            /////MAIN LOOP//////
            foreach (DictionaryEntry de in _beycooInputHash)
            {

                columnTermSet.Clear();

                try
                {
                    string colname = "";
                    colname = de.Key.ToString();

                    //save colname to var so they can be used in OnItemUpdate again
                    columnsForOnUpdate += colname + ";#";

                    if (properties.List.Fields.ContainsField(colname))
                    {
                        //instantiate the taxonomyfield, session and store for the current entity/managed metadata column
                        TaxonomyField tagsField = (TaxonomyField)properties.List.Fields[colname];
                        TaxonomySession session = new TaxonomySession(properties.Web.Site);
                        TermStore termStore = session.TermStores[tagsField.SspId];

                        //get the termSet for the current entity/managed metadata column
                        TermSet termSet = termStore.GetTermSet(tagsField.TermSetId);

                        //create an empty list to collect the terms that are added to the termSet for this entity to facilitate the adding of terms to the target list column as "tags"
                        List<Term> entityTermSet = new List<Term>();

                        //add the terms for this entity from the hashtable hashSubEntities to its own termSet
                        AddTermsToTermSet(termSet, de.Value.ToString(), colname, properties);

                        //add the terms that were added to the columnTermSet to the designated column in the list as "tags"
                        addTermsToColumn(columnTermSet, properties.ListItem, colname, properties);

                        //add columnTermSet to hashtable for onupdate comparison
                        colTermSetForOnupdate.Remove(0, colTermSetForOnupdate.Length);
                        foreach (Term t in columnTermSet)
                        {
                            colTermSetForOnupdate.Append(t.Name.ToString() + "|" + t.Id.ToString() + ";");
                        }
                        setSetting(beyCooConstants.beyCooColTerms + colname, colTermSetForOnupdate.ToString(), properties);

                        //do a CommitAll() per entity/column
                        try
                        {
                            termSet.TermStore.CommitAll();
                        }
                        catch (Exception Exc)
                        {
                            beyCooLogger.LogError("beyCooError", "entityExtraction - " + Exc.Message + Exc.StackTrace);
                        }
                    }

                }
                catch (Exception e)
                {

                    beyCooLogger.LogError("beyCooError", "entityExtraction - " + e.Message + e.StackTrace);
                }
            }
            /////MAIN LOOP////////

            setSetting(beyCooConstants.beyCooCurrentColumns, columnsForOnUpdate, properties);

        }

        private void setSetting(string key, string value, SPItemEventProperties properties)
        {
            properties.Web.AllowUnsafeUpdates = true;
            if (!properties.Web.Properties.ContainsKey(key))
            {
                properties.Web.Properties.Add(key, value);
            }
            else
            {
                properties.Web.Properties[key] = value;
            }
            properties.Web.Properties.Update();
            properties.Web.AllowUnsafeUpdates = false;
        }

        private void fillSetSetting(string key, string value, SPItemEventProperties properties)
        {
            properties.Web.AllowUnsafeUpdates = true;
            if (!properties.Web.Properties.ContainsKey(key))
            {
                properties.Web.Properties.Add(key, value);
            }
            else
            {
                properties.Web.Properties[key] += ";" + value;
            }
            properties.Web.Properties.Update();
            properties.Web.AllowUnsafeUpdates = false;
        }

        /// <summary>
        /// iterate through the hashtable containing the parsed beyCoo results, adding the terms at the "bottom" of each node
        /// </summary>
        /// <param name="termSet"></param>
        /// <param name="hashSubEntities"></param>
        public void AddTermsToTermSet(TermSet termSet, string subentities, string colname, SPItemEventProperties properties)
        {
            int lcid = CultureInfo.CurrentCulture.LCID;
            string[] sepEntities = { ";#" };
            string[] subentitiesArray = subentities.Split(sepEntities, StringSplitOptions.RemoveEmptyEntries);
            AddBottomTerms(termSet, subentitiesArray, colname, properties);

        }


        /// <summary>
        /// method to add the flat list entityTerms (containing all terms that were added to the designated termSet for the current entity/managed metada column) to the taxonomyfield
        /// for the column as "tags"
        /// </summary>
        /// <param name="entityTerms"></param>
        /// <param name="item"></param>
        /// <param name="columnToUpdate"></param>
        /// <param name="properties"></param>
        private void addTermsToColumn(List<Term> entityTerms, SPListItem item, string columnToUpdate, SPItemEventProperties properties)
        {
            properties.Web.AllowUnsafeUpdates = true;
            properties.Web.Site.AllowUnsafeUpdates = true;

            if (properties.ListItem.Fields.ContainsField(columnToUpdate))
            {

                //prepare the terms to be added to the taxonomycolumn in the list
                Converter<Term, string> converter = new Converter<Term, string>(delegate(Term val)
                {
                    return String.Concat(
                        val.GetDefaultLabel(CultureInfo.CurrentCulture.LCID), TaxonomyField.TaxonomyGuidLabelDelimiter, (val.Id));
                });
                string[] stringedTerms = entityTerms.ConvertAll(converter).ToArray();

                //part for debugging
                StringBuilder sb = new StringBuilder();
                foreach (string term in stringedTerms)
                {
                    sb.Append(term + ", ");
                }
                beyCooLogger.LogMessage("beyCooMessage", "items to be added to column: " + sb.ToString());
                //end debugging part

                TaxonomyField tagsField = (TaxonomyField)properties.List.Fields[columnToUpdate];
                if (tagsField.AllowMultipleValues)
                {
                    try
                    {
                        TaxonomyFieldValueCollection tagsValues = new TaxonomyFieldValueCollection(tagsField);
                        tagsValues.PopulateFromLabelGuidPairs(String.Join(TaxonomyField.TaxonomyMultipleTermDelimiter.ToString(), stringedTerms));
                        tagsField.SetFieldValue(item, tagsValues);
                    }
                    catch (Exception e)
                    {
                        beyCooLogger.LogError("beyCooError", "Error adding terms to column!! " + e.Message + " " + e.StackTrace);
                    }
                }

                item.Update();
                EventFiringEnabled = false;
                item.SystemUpdate();
                EventFiringEnabled = true;
            }

            properties.Web.AllowUnsafeUpdates = false;
            properties.Web.Site.AllowUnsafeUpdates = false;
        }



        /// <summary>
        /// helper method to add terms to the current termset, as well as fill the flat collection of terms to be added to the target list as "tags" (columnTermSet)
        /// </summary>
        /// <param name="termSet"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public TermSet AddBottomTerms(TermSet termSet, string[] values, string colname, SPItemEventProperties properties)
        {
            if (properties.Web.Properties.ContainsKey(beyCooConstants.beyCooFreshTerm + colname))
            {
                //set to ""
                setSetting(beyCooConstants.beyCooFreshTerm + colname, "", properties);
            }
            int lcid = CultureInfo.CurrentCulture.LCID;
            beyCooLogger.LogMessage("beyCooMessage", "termsetname : " + termSet.Name + ", " + "termsetowner : " + termSet.Owner);
            StringBuilder sb = new StringBuilder();
            foreach (string term in values)
            {
                sb.Append(term + ", ");
            }
            beyCooLogger.LogMessage("beyCooMessage", "values to be added to termset: " + sb.ToString());
            foreach (string termName in values)
            {
                if (termName.Length > 0)
                {
                    bool exist = false;
                    foreach (Term t in termSet.Terms)
                    {
                        if (t.Name.ToLower() == termName.ToLower())
                        {
                            exist = true;
                            //add all terms from the docterms list to docTermSet, which should contain the docterms as <Terms>
                            columnTermSet.Add(t);
                            break;
                        }
                    }

                    if (exist)
                    {
                        continue;
                    }
                    //add non-existing term to the current termSet
                    try
                    {
                        Term t2 = termSet.CreateTerm(termName, lcid);
                        //save the actually added (new) term to newlyAdded Terms for comparison in OnUpdate
                        //newlyAddedTerms.Add(t2);
                        fillSetSetting(beyCooConstants.beyCooFreshTerm + colname, t2.Name + "|" + t2.Id + ";", properties);

                        beyCooLogger.LogMessage("beyCooMessage", "term to be added to termset: " + termName);
                        //add all terms from the docterms list to docTermSet, which should contain the docterms as <Terms>
                        columnTermSet.Add(t2);
                    }
                    catch (Exception e)
                    {

                        beyCooLogger.LogError("beyCooError", "term could not be added to termset!! " + e.Message + " - " + e.StackTrace);
                    }


                }
            }
            try
            {
                termSet.TermStore.CommitAll();
            }
            catch (Exception ex)
            {
                beyCooLogger.LogError("beyCooError", "AddBottomTerms - " + ex.Message + ex.StackTrace);
            }

            return termSet;
        }


    }
}
